package com.xingu.xg.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xingu.xg.common.consts.ComRT;
import com.xingu.xg.common.consts.ComResult;
import com.xingu.xg.dto.CopyNodeQuery;
import com.xingu.xg.dto.DeleteNodeQuery;
import com.xingu.xg.dto.NodesDto;
import com.xingu.xg.exception.XinGuException;
import com.xingu.xg.mapper.NodesMapper;
import com.xingu.xg.pojo.Nodes;
import com.xingu.xg.service.NodesService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
* @author YY
* @description 针对表【nodes】的数据库操作Service实现
* @createDate 2024-03-11 14:57:35
*/
@Service
@Transactional(rollbackFor = XinGuException.class)
public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes>
    implements NodesService {

    // 未优化
   /* @Override
    public ComResult nodesUp(Integer nodeId) {
        // 1,拿到当前节点信息
        Nodes nodes = getById(nodeId);
        if (nodes == null) throw new XinGuException("该节点不存在");
        Integer sortOrder = nodes.getSortOrder();
        // 2,拿到上一个节点

        Nodes node= getOne(new LambdaQueryWrapper<Nodes>().eq(Nodes::getParentId, nodes.getParentId()).lt(Nodes::getSortOrder,sortOrder).orderByDesc(Nodes::getSortOrder).last("limit 1"));

        if (node == null) {
            // 说明顺序已经在最前
            return ComRT.success();
        }
        // 3, 交换位置
        nodes.setSortOrder(node.getSortOrder());
        node.setSortOrder(sortOrder);
        try {
            updateById(node);
            updateById(nodes);
        } catch (Exception e) {
            throw new XinGuException("服务器正在忙碌中，请稍后再试。");
        }
        return ComRT.success();
    }

    @Override
    public ComResult nodesDown(Integer nodeId) {
        // 1，拿到当前节点信息
        Nodes nodes = getById(nodeId);
        if (nodes == null) throw new XinGuException("该节点不存在");
        Integer sortOrder = nodes.getSortOrder();
        // 2，拿到下一个节点
        Nodes node= getOne(new LambdaQueryWrapper<Nodes>().eq(Nodes::getParentId, nodes.getParentId()).gt(Nodes::getSortOrder,sortOrder).orderByAsc(Nodes::getSortOrder).last("limit 1"));
        // 顺序已经在最后了
        if (node == null) return ComRT.success();
        // 3，交换位置
        nodes.setSortOrder(node.getSortOrder());
        node.setSortOrder(sortOrder);
        try {
            updateById(node);
            updateById(nodes);
        } catch (Exception e) {
            throw new XinGuException("服务器正在忙碌中，请稍后再试。");
        }
        return ComRT.success();
    }*/

    /**
     * 上移动
     * @param nodeId    当前节点id
     * @return
     */
    @Override
    public ComResult nodesUp(Integer nodeId) {
        Nodes nodes = getById(nodeId);
        if (nodes == null) throw new XinGuException("该节点不存在");
        Nodes previousNode = findAdjacentNode(nodes, true);
        if (previousNode == null) {
            // 说明顺序已经在最前
            return ComRT.success();
        }
        swapSortOrders(nodes, previousNode);
        return ComRT.success();
    }

    /**
     * 下移
     * @param nodeId
     * @return
     */
    @Override
    public ComResult nodesDown(Integer nodeId) {
        Nodes nodes = getById(nodeId);
        if (nodes == null) throw new XinGuException("该节点不存在");
        Nodes nextNode = findAdjacentNode(nodes, false);
        if (nextNode == null) {
            // 顺序已经在最后了
            return ComRT.success();
        }
        swapSortOrders(nodes, nextNode);
        return ComRT.success();
    }

    /**
     * 辅助方法，用于交换两个节点的排序值
     */
    private void swapSortOrders(Nodes node1, Nodes node2) {
        if (node1 == null || node2 == null) {
            return;
        }
        Integer tempSortOrder = node1.getSortOrder();
        node1.setSortOrder(node2.getSortOrder());
        node2.setSortOrder(tempSortOrder);
        try {
            updateById(node1);
            updateById(node2);
        } catch (Exception e) {
            throw new XinGuException("服务器正在忙碌中，请稍后再试。");
        }
    }

    /**
     * 辅助方法，用于获取当前节点的上一个或下一个节点
     * @param currentNode    当前节点
     * @param isPrevious     true 上一个   false 下一个
     * @return
     */
    private Nodes findAdjacentNode(Nodes currentNode, boolean isPrevious) {
        LambdaQueryWrapper<Nodes> queryWrapper = new LambdaQueryWrapper<Nodes>()
                .eq(Nodes::getParentId, currentNode.getParentId());

        if (isPrevious) {
            // 查找上一个节点
            queryWrapper.lt(Nodes::getSortOrder, currentNode.getSortOrder()).orderByDesc(Nodes::getSortOrder).last("limit 1");
        } else {
            // 查找下一个节点
            queryWrapper.gt(Nodes::getSortOrder, currentNode.getSortOrder()).orderByAsc(Nodes::getSortOrder).last("limit 1");
        }
        return getOne(queryWrapper);
    }

    @Override
    public ComResult createChildNode(Integer parentId){
        // 1,拿到该节点信息
        Nodes node = getById(parentId);
        if(node==null) throw new XinGuException("该节点不存在");
        // 2，创建子节点
        Nodes childNodes = new Nodes();
        childNodes.setParentId(parentId);
        childNodes.setNodeName("子节点");
        // 2.1顺序放在最前面
        Nodes one = getOne(new LambdaQueryWrapper<Nodes>().eq(Nodes::getParentId, parentId).orderByAsc(Nodes::getSortOrder).last("limit 1"));
        try {
            if(one!=null) {
                childNodes.setSortOrder(one.getSortOrder());
                // 2.2修改兄弟的顺序
                adjustSortOrderRecursive(parentId,one.getSortOrder(),1);
            }
            // 3 新增
            save(childNodes);
        } catch (Exception e) {
            e.printStackTrace();
            throw new XinGuException("服务器正在忙碌中，请稍后再试。");
        }
        return ComRT.success(getById(childNodes.getNodeId()));
    }

    @Override
    public ComResult createParentNode(String childId) {
        // 1,拿到该节点信息
        Nodes childNode = getById(childId);
        if(childNode==null) throw new XinGuException("该节点不存在");
        // 2,创建父节点
        Nodes parentNode = new Nodes();
        parentNode.setNodeName("父节点");
        // 判断是不是在最顶层
        if (childNode.getParentId().intValue()==0) {
            parentNode.setParentId(0);
        }else {
            // 应该找一下之前的父亲
            parentNode.setParentId(childNode.getParentId());
            parentNode.setSortOrder(childNode.getSortOrder());
        }
        try {
            // 保存父节点，是为了拿到id
            save(parentNode);
            parentNode = getById(parentNode.getNodeId());
            childNode.setParentId(parentNode.getNodeId());
            // 更新子节点
            updateById(childNode);
        } catch (Exception e) {
            e.printStackTrace();
            throw new XinGuException("服务器正在忙碌中，请稍后再试。");
        }
        return ComRT.success(parentNode);
    }

    @Override
    public ComResult deleteNode(DeleteNodeQuery deleteNodeQuery) {
        List<String> deleteList = deleteNodeQuery.getDeleteList();
        // 获取并删除指定的节点
        try {
            for (String id : deleteList) {
                Nodes node = getById(id);
                if (node == null) {
                    continue; // 如果节点不存在，则跳过
                }
                // 拿到当前id
                int nodeId = node.getNodeId();
                // 找到子节点
                List<Nodes> children = list(new LambdaQueryWrapper<Nodes>().eq(Nodes::getParentId, nodeId));
                if (!CollectionUtils.isEmpty(children)) {
                    // 更新子节点的ParentId和SortOrder
                    if (node.getParentId() == 0) {
                        children.forEach(n -> n.setParentId(0));
                    } else {
                        AtomicInteger count = new AtomicInteger(0);
                        children.forEach(n -> {
                            n.setParentId(node.getParentId());
                            n.setSortOrder(node.getSortOrder() + count.incrementAndGet());
                        });
                    }
                    // 保证删除后子节点顺序没问题
                    adjustSortOrderRecursive(node.getParentId(), node.getSortOrder()+1, node.getSortOrder() + children.size());
                    updateBatchById(children);
                }
                removeById(id);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new XinGuException("服务器正在忙碌中，请稍后再试。");
        }
        return ComRT.success("节点删除成功");
    }

    @Override
    public ComResult copyNodes(CopyNodeQuery copyNodeQuery) {
        // 0，拿到数据
        String originalId = copyNodeQuery.getOriginalId();
        String originalParentId = copyNodeQuery.getOriginalParentId();
        // 1,拿到原节点的信息
        Nodes originalNode = getById(originalId);
        // 2,复制节点的父节点 与原节点同级
        Nodes copyNode = new Nodes();
        copyNode.setNodeName(originalNode.getNodeName() + "（副本）");
        copyNode.setParentId(Integer.valueOf(originalParentId));
        copyNode.setSortOrder(originalNode.getSortOrder() + 1);
        // 问题1 原来节点的兄弟节点顺序 +1
        adjustSortOrderRecursive(Integer.valueOf(originalParentId), originalNode.getSortOrder()+1, 1);
        // 2.1,添加父节点
        save(copyNode);
        // 3，拿到所有需要复制的子节点
        List<Nodes> copiedNodes = null;
        try {
            copiedNodes = copySubNodes(originalNode, copyNode.getNodeId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new XinGuException("服务器正在忙碌中，请稍后再试。");
        }
        return ComRT.success();
    }

    /**
     * 递归复制子节点
     * @param original 原始节点
     * @param newParentId 新的父节点ID
     * @return 复制的节点列表
     */
    private List<Nodes> copySubNodes(Nodes original, int newParentId) {
        List<Nodes> copiedNodes = new ArrayList<>();
        // 获取原始节点的所有子节点
        List<Nodes> children = list(new LambdaQueryWrapper<Nodes>().eq(Nodes::getParentId,original.getNodeId()));
        for (Nodes child : children) {
            Nodes copiedChild = new Nodes();
            copiedChild.setNodeName(child.getNodeName());
            copiedChild.setParentId(newParentId);
            copiedChild.setSortOrder(child.getSortOrder());
            // 保存当前复制的节点  需要拿到自增id
            save(copiedChild);
            // 递归复制子节点的子节点
            List<Nodes> grandChildren = copySubNodes(child, copiedChild.getNodeId());
            copiedNodes.addAll(grandChildren); // 将子节点的复制结果添加到列表中
        }
        return copiedNodes;
    }

    /**
     * 调整兄弟节点的顺序  比如突然插入一个父节点，或者复制节点
     * @param parentId  父id
     * @param order     排序号
     * @param orderNum  排序号 + orderNum
     */
    @Override
    public void adjustSortOrderRecursive(Integer parentId,Integer order,int orderNum){
        List<Nodes> list = list(new LambdaQueryWrapper<Nodes>().eq(Nodes::getParentId, parentId).ge(Nodes::getSortOrder, order));
        list.forEach(n ->n.setSortOrder(n.getSortOrder()+orderNum));
        updateBatchById(list);
    }

}




